Palindrome linked list

Time: O(N); Space: O(1); easy

Given a singly linked list, determine if it is a palindrome.

Example 1:

Input: head = {ListNode} 1->2->None

Output: False

Example 2:

Input: head = {ListNode} 1->2->2->1->None

Output: True

Follow up:

  • Could you do it in O(n) time and O(1) space?

[1]:
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

    def __repr__(self):
        if self:
            return "{} -> {}".format(self.val, repr(self.next))
[2]:
class Solution1(object):
    """
    Time: O(N)
    Space: O(1)
    """
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: boolean
        """
        reverse, fast = None, head

        # Reverse the first half part of the list.
        while fast and fast.next:
            fast = fast.next.next
            head.next, reverse, head = reverse, head, head.next

        # If the number of the nodes is odd,
        # set the head of the tail list to the next of the median node.
        tail = head.next if fast else head

        # Compare the reversed first half list with the second half list.
        # And restore the reversed first half list.
        is_palindrome = True
        while reverse:
            is_palindrome = is_palindrome and reverse.val == tail.val
            reverse.next, head, reverse = head, reverse, reverse.next
            tail = tail.next

        return is_palindrome
[3]:
s = Solution1()

head = ListNode(1)
head.next = ListNode(2)
assert s.isPalindrome(head) == False

head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(2)
head.next.next.next = ListNode(1)
assert s.isPalindrome(head) == True